package formatter

import (
    "fmt"
    "strings"
    "time"

    "sysinfo/internal/types"
)

// FormatText 将信息格式化为纯文本
func FormatText(info *types.SystemInfo) string {
	var sb strings.Builder

	sb.WriteString(fmt.Sprintf("时间戳: %s\n\n", info.Timestamp.Format("2006-01-02 15:04:05")))

	// 系统信息
	if info.System != nil {
		sb.WriteString("系统信息\n")
		sb.WriteString(fmt.Sprintf("主机名: %s\n", info.System.Hostname))
		sb.WriteString(fmt.Sprintf("操作系统: %s\n", info.System.OS))
		sb.WriteString(fmt.Sprintf("平台: %s %s\n", info.System.Platform, info.System.PlatformVersion))
		sb.WriteString(fmt.Sprintf("平台系列: %s\n", info.System.PlatformFamily))
		sb.WriteString(fmt.Sprintf("内核: %s (%s)\n", info.System.KernelVersion, info.System.KernelArch))
		sb.WriteString(fmt.Sprintf("运行时间: %s\n", info.System.UptimeFormatted))
		sb.WriteString(fmt.Sprintf("进程数: %d\n\n", info.System.Procs))
	}

	// CPU信息
	if info.CPU != nil {
		sb.WriteString("CPU信息\n")
		sb.WriteString(fmt.Sprintf("型号: %s\n", info.CPU.ModelName))
		sb.WriteString(fmt.Sprintf("制造商: %s\n", info.CPU.Vendor))
		sb.WriteString(fmt.Sprintf("物理核心: %d\n", info.CPU.Cores))
		sb.WriteString(fmt.Sprintf("逻辑CPU: %d\n", info.CPU.LogicalCPUs))
		sb.WriteString(fmt.Sprintf("频率: %.2f MHz\n", info.CPU.MHz))
		if info.CPU.LoadAvg != nil {
			sb.WriteString(fmt.Sprintf("负载平均值: %.2f, %.2f, %.2f\n",
				info.CPU.LoadAvg.Load1, info.CPU.LoadAvg.Load5, info.CPU.LoadAvg.Load15))
		}
		if len(info.CPU.Usage) > 0 {
			sb.WriteString("每个核心的CPU使用率:\n")
			for i, usage := range info.CPU.Usage {
				sb.WriteString(fmt.Sprintf("  核心 %d: %.2f%%\n", i, usage))
			}
		}
		sb.WriteString("\n")
	}

	// 内存信息
	if info.Memory != nil {
		sb.WriteString("内存信息\n")
		sb.WriteString(fmt.Sprintf("总量: %s\n", info.Memory.TotalFormatted))
		sb.WriteString(fmt.Sprintf("已用: %s (%.2f%%)\n", info.Memory.UsedFormatted, info.Memory.UsedPercent))
		sb.WriteString(fmt.Sprintf("可用: %s\n", info.Memory.FreeFormatted))
		if info.Memory.SwapTotal > 0 {
			sb.WriteString(fmt.Sprintf("交换区总量: %s\n", formatBytes(info.Memory.SwapTotal)))
			sb.WriteString(fmt.Sprintf("交换区已用: %s (%.2f%%)\n", formatBytes(info.Memory.SwapUsed), info.Memory.SwapPercent))
		}
		sb.WriteString("\n")
	}

	// 存储信息
	if info.Disk != nil {
		sb.WriteString("存储信息\n")

		// Physical disks
		if len(info.Disk.PhysicalDisks) > 0 {
			sb.WriteString("Physical Disks:\n")
			for _, disk := range info.Disk.PhysicalDisks {
				diskType := disk.Type
				if diskType == "" {
					diskType = "Unknown"
				}
				sb.WriteString(fmt.Sprintf("  %s [%s", disk.Name, diskType))
				if disk.Interface != "" {
					sb.WriteString(fmt.Sprintf(" - %s", disk.Interface))
				}
				sb.WriteString("]\n")

				if disk.Model != "" {
					sb.WriteString(fmt.Sprintf("    Model: %s\n", disk.Model))
				}
				if disk.SizeFormatted != "" && disk.SizeFormatted != "N/A" {
					sb.WriteString(fmt.Sprintf("    Size: %s\n", disk.SizeFormatted))
				}
				if disk.SerialNumber != "" {
					sb.WriteString(fmt.Sprintf("    Serial: %s\n", disk.SerialNumber))
				}
				if disk.RPM > 0 {
					sb.WriteString(fmt.Sprintf("    RPM: %d\n", disk.RPM))
				}
				if disk.Removable {
					sb.WriteString("    Removable: Yes\n")
				}
			}
			sb.WriteString("\n")
		}

		// Mounted partitions (filter loop devices)
		if len(info.Disk.Partitions) > 0 {
			var significantPartitions []types.PartitionInfo
			for _, part := range info.Disk.Partitions {
				if strings.HasPrefix(part.Device, "/dev/loop") || part.FSType == "squashfs" {
					continue
				}
				significantPartitions = append(significantPartitions, part)
			}

			if len(significantPartitions) > 0 {
				sb.WriteString("Mounted Partitions:\n")
				for _, part := range significantPartitions {
					sb.WriteString(fmt.Sprintf("  %s", part.Device))
					if part.MountPoint != "" {
						sb.WriteString(fmt.Sprintf(" → %s", part.MountPoint))
					}
					sb.WriteString("\n")
					sb.WriteString(fmt.Sprintf("    Type: %s\n", part.FSType))
					sb.WriteString(fmt.Sprintf("    Total: %s\n", part.TotalFormatted))
					sb.WriteString(fmt.Sprintf("    Used: %s (%.2f%%)\n", part.UsedFormatted, part.UsedPercent))
					sb.WriteString(fmt.Sprintf("    Free: %s\n", part.FreeFormatted))
				}
			}
		}
		sb.WriteString("\n")
	}

	// SMART disk health information
	if info.Disk != nil && len(info.Disk.SMARTData) > 0 {
		sb.WriteString("SMART DISK HEALTH\n")
		for _, smart := range info.Disk.SMARTData {
			deviceName := smart.Device
			if smart.DeviceModel != "" {
				deviceName = smart.DeviceModel
			}

			healthStatus := "HEALTHY"
			if !smart.Healthy {
				healthStatus = "WARNING"
			}

			sb.WriteString(fmt.Sprintf("Device: %s [%s]\n", deviceName, healthStatus))

			if smart.Serial != "" {
				sb.WriteString(fmt.Sprintf("  Serial: %s\n", smart.Serial))
			}
			if smart.ModelFamily != "" {
				sb.WriteString(fmt.Sprintf("  Model Family: %s\n", smart.ModelFamily))
			}
			if smart.Capacity > 0 {
				sb.WriteString(fmt.Sprintf("  Capacity: %s\n", formatBytes(smart.Capacity)))
			}
			if smart.Temperature > 0 {
				sb.WriteString(fmt.Sprintf("  Temperature: %d°C\n", smart.Temperature))
			}
			if smart.PowerOnHours > 0 {
				days := smart.PowerOnHours / 24
				sb.WriteString(fmt.Sprintf("  Power-On Hours: %d (%d days)\n", smart.PowerOnHours, days))
			}

			// Display key SMART attributes
			if len(smart.Attributes) > 0 {
				criticalAttrs := []string{
					"Reallocated_Sector_Count",
					"Current_Pending_Sector",
					"Offline_Uncorrectable",
					"UDMA_CRC_Error_Count",
					"SMART",
					"Status",
				}

				hasShownAttrs := false
				for _, attrName := range criticalAttrs {
					if val, ok := smart.Attributes[attrName]; ok {
						if !hasShownAttrs {
							sb.WriteString("  Attributes:\n")
							hasShownAttrs = true
						}
						sb.WriteString(fmt.Sprintf("    %s: %s\n", attrName, val))
					}
				}
			}
			sb.WriteString("\n")
		}
	}

	// Network information
	if info.Network != nil && len(info.Network.Interfaces) > 0 {
		sb.WriteString("NETWORK INTERFACES\n")
		for _, iface := range info.Network.Interfaces {
			sb.WriteString(fmt.Sprintf("Interface: %s\n", iface.Name))
			if iface.HardwareAddr != "" {
				sb.WriteString(fmt.Sprintf("  MAC: %s\n", iface.HardwareAddr))
			}
			if len(iface.Addresses) > 0 {
				sb.WriteString(fmt.Sprintf("  Addresses: %s\n", strings.Join(iface.Addresses, ", ")))
			}
			if len(iface.Flags) > 0 {
				sb.WriteString(fmt.Sprintf("  Flags: %s\n", strings.Join(iface.Flags, ", ")))
			}
			sb.WriteString(fmt.Sprintf("  MTU: %d\n", iface.MTU))
			if iface.BytesSent > 0 || iface.BytesRecv > 0 {
				sb.WriteString(fmt.Sprintf("  Bytes Sent: %s\n", formatBytes(iface.BytesSent)))
				sb.WriteString(fmt.Sprintf("  Bytes Received: %s\n", formatBytes(iface.BytesRecv)))
			}
		}
		sb.WriteString("\n")
	}

	// Port usage information
	if info.Ports != nil {
		sb.WriteString("PORT USAGE\n")
		sb.WriteString(fmt.Sprintf("Total Listening: %d\n", info.Ports.TotalListening))
		max := len(info.Ports.Entries)
		if max > 50 {
			max = 50
		}
		for i := 0; i < max; i++ {
			e := info.Ports.Entries[i]
			ip := e.LocalIP
			if ip == "" {
				ip = "0.0.0.0"
			}
			pidStr := ""
			if e.PID > 0 {
				pidStr = fmt.Sprintf(" PID %d", e.PID)
			}
			procStr := ""
			if e.ProcessName != "" {
				procStr = fmt.Sprintf(" (%s)", e.ProcessName)
			}
			sb.WriteString(fmt.Sprintf("  %s %s:%d%s%s\n", strings.ToUpper(e.Protocol), ip, e.LocalPort, pidStr, procStr))
		}
		sb.WriteString("\n")
	}

	// Process information
	if info.Processes != nil {
		sb.WriteString("PROCESS INFORMATION\n")
		sb.WriteString(fmt.Sprintf("Total: %d (Running: %d, Sleeping: %d)\n",
			info.Processes.TotalCount, info.Processes.Running, info.Processes.Sleeping))

		if len(info.Processes.TopByMemory) > 0 {
			sb.WriteString("\nTop Processes by Memory:\n")
			for i, proc := range info.Processes.TopByMemory {
				if i >= 5 {
					break
				}
				sb.WriteString(fmt.Sprintf("  %s (PID %d): %d MB (%.2f%%)\n",
					proc.Name, proc.PID, proc.MemoryMB, proc.MemoryPercent))
			}
		}

		if len(info.Processes.TopByCPU) > 0 {
			sb.WriteString("\nTop Processes by CPU:\n")
			for i, proc := range info.Processes.TopByCPU {
				if i >= 5 {
					break
				}
				sb.WriteString(fmt.Sprintf("  %s (PID %d): %.2f%%\n",
					proc.Name, proc.PID, proc.CPUPercent))
			}
		}
		sb.WriteString("\n")
	}

	// Battery information
	if info.Battery != nil && info.Battery.Present && len(info.Battery.Batteries) > 0 {
		sb.WriteString("BATTERY INFORMATION\n")

		powerSource := "AC Power"
		if info.Battery.OnBattery {
			powerSource = "Battery Power"
		}
		sb.WriteString(fmt.Sprintf("Power Source: %s\n", powerSource))

		if len(info.Battery.Batteries) > 1 {
			sb.WriteString(fmt.Sprintf("Total Capacity: %s\n", formatMilliwattHours(info.Battery.TotalCapacity)))
		}

		for _, battery := range info.Battery.Batteries {
			batteryLabel := battery.Name
			if battery.Model != "" {
				batteryLabel = fmt.Sprintf("%s (%s)", battery.Name, battery.Model)
			}
			sb.WriteString(fmt.Sprintf("\n%s\n", batteryLabel))

			sb.WriteString(fmt.Sprintf("  State: %s\n", battery.State))

			if battery.ChargeLevel > 0 {
				sb.WriteString(fmt.Sprintf("  Charge Level: %.1f%%\n", battery.ChargeLevel))
			}

			if battery.Health > 0 {
				sb.WriteString(fmt.Sprintf("  Battery Health: %.1f%%\n", battery.Health))
			}

			if battery.TimeRemaining >= 0 {
				timeStr := formatTime(battery.TimeRemaining)
				if battery.IsCharging {
					sb.WriteString(fmt.Sprintf("  Time to Full: %s\n", timeStr))
				} else if battery.IsDischarging {
					sb.WriteString(fmt.Sprintf("  Time Remaining: %s\n", timeStr))
				}
			}

			if battery.CapacityFull > 0 {
				sb.WriteString(fmt.Sprintf("  Current Capacity: %s / %s\n",
					formatMilliwattHours(battery.CapacityNow),
					formatMilliwattHours(battery.CapacityFull)))
			}

			if battery.Capacity > 0 && battery.Capacity != battery.CapacityFull {
				sb.WriteString(fmt.Sprintf("  Design Capacity: %s\n", formatMilliwattHours(battery.Capacity)))
			}

			if battery.Voltage > 0 {
				sb.WriteString(fmt.Sprintf("  Voltage: %.2f V\n", battery.Voltage))
			}

			if battery.PowerNow > 0 {
				powerLabel := "Power Draw"
				if battery.IsCharging {
					powerLabel = "Charge Rate"
				}
				sb.WriteString(fmt.Sprintf("  %s: %.2f W\n", powerLabel, float64(battery.PowerNow)/1000.0))
			}

			if battery.Temperature > 0 {
				sb.WriteString(fmt.Sprintf("  Temperature: %.1f°C\n", battery.Temperature))
			}

			if battery.CycleCount > 0 {
				sb.WriteString(fmt.Sprintf("  Cycle Count: %d\n", battery.CycleCount))
			}

			if battery.Vendor != "" {
				sb.WriteString(fmt.Sprintf("  Manufacturer: %s\n", battery.Vendor))
			}

			if battery.Technology != "" {
				sb.WriteString(fmt.Sprintf("  Technology: %s\n", battery.Technology))
			}

			if battery.SerialNumber != "" {
				sb.WriteString(fmt.Sprintf("  Serial Number: %s\n", battery.SerialNumber))
			}
		}
		sb.WriteString("\n")
	}

    // GPU information
    if info.GPU != nil && len(info.GPU.GPUs) > 0 {
        sb.WriteString("GPU INFORMATION\n")
        for _, gpu := range info.GPU.GPUs {
            sb.WriteString(fmt.Sprintf("GPU %d: %s\n", gpu.Index, gpu.Name))
			if gpu.Vendor != "" {
				sb.WriteString(fmt.Sprintf("  Vendor: %s\n", gpu.Vendor))
			}
			if gpu.Driver != "" {
				sb.WriteString(fmt.Sprintf("  Driver: %s", gpu.Driver))
				if gpu.DriverVersion != "" {
					sb.WriteString(fmt.Sprintf(" (Version: %s)", gpu.DriverVersion))
				}
				sb.WriteString("\n")
			}
			if gpu.MemoryTotal > 0 {
				sb.WriteString(fmt.Sprintf("  Memory: %s", gpu.MemoryFormatted))
				if gpu.MemoryUsed > 0 {
					usedPercent := float64(gpu.MemoryUsed) / float64(gpu.MemoryTotal) * 100
					sb.WriteString(fmt.Sprintf(" (Used: %s, %.1f%%)", formatBytes(gpu.MemoryUsed), usedPercent))
				}
				sb.WriteString("\n")
			}
			if gpu.Temperature > 0 {
				sb.WriteString(fmt.Sprintf("  Temperature: %d°C\n", gpu.Temperature))
			}
			if gpu.Utilization > 0 {
				sb.WriteString(fmt.Sprintf("  GPU Utilization: %d%%\n", gpu.Utilization))
			}
			if gpu.MemoryUtilization > 0 {
				sb.WriteString(fmt.Sprintf("  Memory Utilization: %d%%\n", gpu.MemoryUtilization))
			}
			if gpu.PowerDraw > 0 {
				sb.WriteString(fmt.Sprintf("  Power Draw: %.1f W", gpu.PowerDraw))
				if gpu.PowerLimit > 0 {
					sb.WriteString(fmt.Sprintf(" / %.1f W", gpu.PowerLimit))
				}
				sb.WriteString("\n")
			}
			if gpu.ClockSpeed > 0 {
				sb.WriteString(fmt.Sprintf("  Clock Speed: %d MHz\n", gpu.ClockSpeed))
			}
			if gpu.FanSpeed > 0 {
				sb.WriteString(fmt.Sprintf("  Fan Speed: %d%%\n", gpu.FanSpeed))
			}
			if gpu.PCIBus != "" {
				sb.WriteString(fmt.Sprintf("  PCI Bus: %s\n", gpu.PCIBus))
			}
        }
        sb.WriteString("\n")
    }

    // 最近活动
    if info.Activity != nil {
        if len(info.Activity.RecentProcesses) > 0 {
            sb.WriteString("RECENTLY STARTED PROCESSES\n")
            max := len(info.Activity.RecentProcesses)
            if max > 15 { max = 15 }
            for i := 0; i < max; i++ {
                p := info.Activity.RecentProcesses[i]
                ts := time.UnixMilli(p.CreateTime).Format("2006-01-02 15:04:05")
                name := p.Name
                if name == "" { name = "(unknown)" }
                sb.WriteString(fmt.Sprintf("  [%s] %s (PID %d)\n", ts, name, p.PID))
            }
            sb.WriteString("\n")
        }

        if len(info.Activity.RecentFiles) > 0 {
            sb.WriteString("RECENTLY ACCESSED FILES\n")
            max := len(info.Activity.RecentFiles)
            if max > 15 { max = 15 }
            for i := 0; i < max; i++ {
                f := info.Activity.RecentFiles[i]
                disp := f.DisplayName
                if disp == "" { disp = f.Path }
                sb.WriteString(fmt.Sprintf("  [%s] %s\n", f.OpenedTime.Format("2006-01-02 15:04:05"), disp))
            }
            sb.WriteString("\n")
        }
    }

    return sb.String()
}

func formatBytes(bytes uint64) string {
	const unit = 1024
	if bytes < unit {
		return fmt.Sprintf("%d B", bytes)
	}

	div, exp := uint64(unit), 0
	for n := bytes / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}

	units := []string{"KB", "MB", "GB", "TB", "PB", "EB"}
	return fmt.Sprintf("%.2f %s", float64(bytes)/float64(div), units[exp])
}
